package cn.wgx.modules.sys.services;

import cn.wgx.commons.util.ReflectionUtils;
import cn.wgx.commons.util.StringUtils;
import cn.wgx.commons.util.Validation;
import cn.wgx.modules.base.entity.BaseEntity;
import cn.wgx.modules.base.entity.BaseFavoriteAndLikeEntity;
import cn.wgx.modules.base.services.BaseService;
import cn.wgx.modules.sys.entity.SysUserFavorite;
import cn.wgx.modules.sys.entity.SysUserFavoriteExample;
import cn.wgx.modules.sys.entity.mapper.SysUserFavoriteExtendMapper;
import cn.wgx.modules.sys.entity.mapper.SysUserFavoriteMapper;
import cn.wgx.modules.sys.entity.shortentity.ShortSysUser;
import cn.wgx.modules.sys.util.UserUtil;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Service
public class SysUserFavoriteService extends BaseService<SysUserFavorite> {

    public static final String cacheName = "FavoriteService";
    public static final String cacheKeyPre = "fav_";
    @Resource
    SysUserFavoriteMapper mapper;

    @Resource
    SysUserFavoriteExtendMapper sysUserFavoriteExtendMapper;



    @Autowired
    SysUserLikeService sysUserLikeService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Transactional(readOnly = true)
    public List<SysUserFavorite> getList(SysUserFavorite record, Boolean desc) {
        SysUserFavoriteExample example = new SysUserFavoriteExample();
        if (record != null) {
            SysUserFavoriteExample.Criteria criteria = example.createCriteria();
            if (record.getUser_id() != null) {
                criteria.andUser_idEqualTo(record.getUser_id());
            }
            if (record.getType() != null) {
                criteria.andTypeEqualTo(record.getType());
            }
            if (record.getRes_id() != null) {
                criteria.andRes_idEqualTo(record.getRes_id());
            }
            if (record.getFavorite_id() != null) {
                criteria.andFavorite_idEqualTo(record.getFavorite_id());
            }
            if(StringUtils.isNotBlank(record.getTitle())){
                criteria.andTitleLike("%" + record.getTitle() + "%");
            }
            addPublicCondition(record, criteria);
        }
        example.setOrderByClause("createDate " + (desc ? "desc" : "asc"));
        return mapper.selectByExample(example);
    }

    //统计某人收藏的所有类型的数量
    //    @Cacheable(value = cacheName, unless = "#result == null", key = "#root.target.getCachePreKey() + \"_\" + #type + \"_\" + #user_id")
    @Transactional(readOnly = true)
    public Map getAllCount(Integer user_id) {
        return sysUserFavoriteExtendMapper.getFavAllCountByUserId(user_id);
    }

    //统计某资源被收藏次数
    @Transactional(readOnly = true)
    public Integer getCountByResId(Integer res_id, Integer type) {
        return sysUserFavoriteExtendMapper.getFavCountResId(res_id, type);
    }

    //统计某人收藏某类型次数
    @Transactional(readOnly = true)
    public Integer getCountByUserId(Integer user_id, Integer type) {
        return sysUserFavoriteExtendMapper.getFavCountByUserId(user_id, type);
    }

    //更新无title的数据
    //#update `sys_user_favorite` a , edu_course b set a.title = b.course_task where a.res_id = b.course_id and a.type = 1
    //update `sys_user_favorite` a , edu_course_assignment_his b set a.title = b.answer where a.res_id = b.assignment_his_id and a.type = 2
    //update `sys_user_favorite` a , edu_course_note b set a.title = b.title where a.res_id = b.course_note_id and a.type = 3
    //1课程,2作业,3笔记,4关注的人
    @Transactional(readOnly = true)
    public List getListByType(SysUserFavorite record, Boolean desc, String targetIdName) {
        List<SysUserFavorite> list = getList(record, desc);
        List<Integer> idList = getIntegerIdList(list, targetIdName == null ? "res_id" : targetIdName);
        Integer type = record.getType();
        switch (type) {

            default:
                return emptyList;
        }
    }

    //统计人员粉丝和关注数量
    public void wrapFollow(ShortSysUser shortSysUser, Integer user_id) {
        if (shortSysUser == null || Validation.isNullOrZero(shortSysUser.getUser_id())) {
            return;
        }
        //粉丝数量
        Integer fansNum = getCountByResId(shortSysUser.getUser_id(), 4);
        //关注他人数量
        Integer followNum = getCountByUserId(shortSysUser.getUser_id(), 4);
        SysUserFavorite one = getOne(user_id, shortSysUser.getUser_id(), 4);
        if(one != null){
            shortSysUser.setHasFollow(true);
        }
        shortSysUser.setFansNum(fansNum);
        shortSysUser.setFollowNum(followNum);
    }

    //按收藏时间排序

    /**
     *
     * @param list
     * @param list2
     * @return
     */
    private List sort(List<? extends BaseEntity> list, List<SysUserFavorite> list2) {
        List<BaseEntity> newList = Lists.newArrayList();
        for (int i = 0, n = list2.size(); i < n; i++) {
            Integer res_id = list2.get(i).getRes_id();
            for (int j = 0, m = list.size(); j < m; j++) {
                BaseEntity baseEntity = list.get(j);
                Integer resId = 0;

                if (res_id.equals(resId)) {
                    newList.add(baseEntity);
                    list.remove(j);
                    break;
                }
            }
        }
        return newList;
//        for(int i=0,n=list2.size(),x=0,m=list.size();i<n;i++){
//            Integer res_id = list2.get(i).getRes_id();
//            for(int j=x+1;j<m;j++){
//                BaseEntity baseEntity = list.get(j);
//                Integer resId = 0;
//                if(baseEntity instanceof EduCourse){
//                    resId = ((EduCourse)baseEntity).getCourse_id();
//                }else if(baseEntity instanceof EduCourseNote){
//                    resId = ((EduCourseNote)baseEntity).getCourse_note_id();
//                }else if(baseEntity instanceof EduCourseAssignment){
//                    resId = ((EduCourseAssignment)baseEntity).getAssignment_id();
//                }
//                if(res_id.equals(resId)){
//                    BaseEntity baseEntity1 = list.get(x);
//
//                    x++;
//                }
//            }
//        }
    }

    public void wrapFavorite(List<? extends BaseFavoriteAndLikeEntity> targetList, Integer type, String idName, Integer user_id) {
        wrapHasFavorite(targetList, type, idName, user_id);
        wrapFavoriteNum(targetList, type, idName);
    }


    //包装检测我是否已收藏此资源
    private void wrapHasFavorite(List<? extends BaseFavoriteAndLikeEntity> targetList, Integer type, String idName, Integer user_id) {
        if (Validation.isNullOrZero(user_id) || !(type == 1 || type == 2 || type == 3 || type == 4)
                || targetList == null || targetList.isEmpty()) {
            return;
        }
        List<Integer> ids = getIntegerIdList(targetList, idName);
        SysUserFavoriteExample example = new SysUserFavoriteExample();
        example.createCriteria().andRes_idIn(ids).andTypeEqualTo(type).andUser_idEqualTo(user_id);
        List<SysUserFavorite> sysUserFavorites = mapper.selectByExample(example);
        for (int i = 0, n = sysUserFavorites.size(), m = targetList.size(); i < n; i++) {
            for (int j = 0; j < m; j++) {
                BaseFavoriteAndLikeEntity baseFavoriteEntity = targetList.get(j);
                if (sysUserFavorites.get(i).getRes_id().equals(ReflectionUtils.getValueByFieldName(baseFavoriteEntity, idName))) {
                    baseFavoriteEntity.setFav(true);
                }
            }
        }
    }

    //检测每个资源被收藏的数量
    private void wrapFavoriteNum(List<? extends BaseFavoriteAndLikeEntity> targetList, Integer type, String idName) {
        if (targetList == null || targetList.isEmpty()) {
            return;
        }
        List<Integer> ids = getIntegerIdList(targetList, idName);
        int n = ids.size();
        String keyPre = getCacheKeyPre(type);
        List<String> idsStr = new ArrayList<>();
        for (Integer id : ids) {
            idsStr.add(keyPre + id);
        }
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        List<String> resList = stringStringValueOperations.multiGet(idsStr);//批量取出结果
        if (resList != null && resList.size() == n) {
            for (int i = 0; i < n; i++) {
                Object o = resList.get(i);
                if (o == null) {
                    Integer integer = ids.get(i);
                    Integer countByRes_id = getCountByResId(integer, type);
                    resList.set(i, countByRes_id + "");
                    stringStringValueOperations.set(keyPre + integer, countByRes_id + "");
                }
            }
        }
        for (int i = 0, m = targetList.size(); i < n; i++) {
            for (int j = 0; j < m; j++) {
                BaseFavoriteAndLikeEntity baseFavoriteEntity = targetList.get(j);
                if (ids.get(i).equals(ReflectionUtils.getValueByFieldName(baseFavoriteEntity, idName))) {
                    baseFavoriteEntity.setFavoriteNum(Integer.parseInt(resList.get(i)));
                }
            }
        }
    }

    public List<Integer> checkHas(List<Integer> ids, Integer type) {
        SysUserFavoriteExample example = new SysUserFavoriteExample();
        SysUserFavoriteExample.Criteria criteria = example.createCriteria();
        criteria.andRes_idIn(ids).andTypeEqualTo(type).andUser_idEqualTo(UserUtil.getUser().getUser_id());
        List<SysUserFavorite> sysUserFavorites = mapper.selectByExample(example);
        return getIntegerIdList(sysUserFavorites, "res_id");
    }

    //1课程,2作业,3笔记
    public boolean checkHas(Integer type, Integer res_id) {
        switch (type) {
        }
        return false;
    }
    public String getTitle(Object o , Integer type){
        if(o == null){
            return "";
        }
        return "";
    }

    @Override
    @Transactional(readOnly = true)
    public List<SysUserFavorite> getListByIds(List<Integer> ids) {
        if (ids == null || ids.isEmpty()) {
            return null;
        }
        SysUserFavoriteExample example = new SysUserFavoriteExample();
        example.createCriteria().andFavorite_idIn(ids);
        return mapper.selectByExample(example);
    }


    @Transactional(readOnly = true)
    public SysUserFavorite getOne(Integer user_id, Integer type, Integer res_id) {
        SysUserFavorite record = new SysUserFavorite();
        record.setUser_id(user_id);
        record.setType(type);
        record.setRes_id(res_id);
        List<SysUserFavorite> list = getList(record, true);
        if (list != null && !list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }


    @Transactional
//    @CacheEvict(value = cacheName, key = "#root.target.getCachePreKey() + \"_\" + #record.getType() + \"_\" + #record.getUser_id()")
    public SysUserFavorite insertOne(SysUserFavorite record) {
        filter(record, true);
        int i = mapper.insertSelective(record);
        record.set_result(i);
        if (i > 0) {
            new Thread(() -> {
                ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
                String k = getCacheKeyPre(record.getType()) + record.getRes_id();
                if (stringStringValueOperations.get(k) != null) {
                    stringStringValueOperations.increment(k);
                }
            }).start();
        }
        return record;
    }


    @Transactional
//    @CacheEvict(value = cacheName, key = "#root.target.getCachePreKey() + \"_\" + #type  + \"_\" + #user_id")
    public int deleteOne(Integer user_id, Integer type, Integer res_id) {
        SysUserFavoriteExample example = new SysUserFavoriteExample();
        example.createCriteria().andUser_idEqualTo(user_id).andTypeEqualTo(type).andRes_idEqualTo(res_id);
        int i = mapper.deleteByExample(example);
        if (i > 0) {
            new Thread(() -> {
                ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
                String k = getCacheKeyPre(type) + res_id;
                if (stringStringValueOperations.get(k) != null) {
                    stringStringValueOperations.decrement(k);
                }
            }).start();
        }
        return i;
    }

    private String getCacheKeyPre(Integer type) {
        return cacheKeyPre + type + "_";
    }

}
